//
// Created by lijinpeng on 2022/4/3.
//

#include <QJsonObject>
#include <QJsonArray>
#include "Display.h"
#include "QFile"
#include "QJsonDocument"

shared_ptr<Display> Display::FromFile(const QString &file_path) {
    QFile file(file_path);
    file.open(QIODevice::ReadOnly | QIODevice::Text);
    auto text = file.readAll();
    file.close();
    QJsonParseError error;
    QJsonDocument document = QJsonDocument::fromJson(text, &error);
    if (error.error != QJsonParseError::NoError) {
        return nullptr;
    }
    DisplayPtr display = make_shared<Display>();

    auto root_obj = document.object();

    display = ParserColor(display, root_obj);

    display = ParserStipper(display, root_obj);


    display = ParserLineStyle(display, root_obj);

    display = ParserPacket(display, root_obj);

    return display;

}

DisplayPtr &Display::ParserPacket(DisplayPtr &display, const QJsonObject &root_obj) {
    auto packet_array = root_obj["drDefinePacket"].toArray();
    for(auto packet_item : packet_array)
    {
        auto packet_info = packet_item.toArray();
        Packet packet{};
        packet.name = packet_info[1].toString();
        packet.stipple_name = packet_info[2].toString();
        packet.line_style_name = packet_info[3].toString();
        packet.fill_color_name = packet_info[4].toString();
        packet.out_line_color_name = packet_info[5].toString();
        packet.fill_style_name = ParserFillStyle(packet_info[6].toString());
        QBrush brush;
        if(packet.stipple_name == "blank")
        {
            brush = QBrush(Qt::NoBrush);
        }else
        {
            if(display->Stipples.contains(packet.name))
            {
                const Stipple & stipple = display->Stipples[packet.name];
                QImage img(stipple.width  ,stipple.height , QImage::Format_ARGB32);
                auto fill_color = display->Colors[packet.fill_color_name];
                QColor transparent_color = QColor::fromRgb(255,255,255,0);
                for(int i ; i < stipple.height ; i++)
                {
                    for(int j ; j < stipple.width ; j++)
                    {
                        int value = stipple.bitmap[i][j];
                        if(value == 1)
                        {
                            img.setPixel(j , i , fill_color.color.rgba());
                        }
                        else
                        {
                            img.setPixel(j , i ,transparent_color.rgba());
                        }
                    }
                }
                brush = QBrush(img);
            }
            else
            {
                brush = QBrush(Qt::NoBrush);
            }
        }

        packet.brush = brush;
        QPen pen = QPen(display->Colors[packet.out_line_color_name].color);
        if(packet.line_style_name != "solid")
        {
            auto style = display->LineStyles[packet.line_style_name];
            pen.setWidth(style.size);
            pen.setCosmetic(true);
            pen.setDashPattern(style.pattern);
        }
        display->Packets[packet.name.toLower()] = packet;
    }
    return display;
}

DisplayPtr &Display::ParserLineStyle(DisplayPtr &display, const QJsonObject &root_obj) {
    auto line_style_array = root_obj["drDefineLineStyle"].toArray();
    for (auto line_style_item: line_style_array){
        auto line_style_info = line_style_item.toArray();

        QVector<double> pattern;
        for(auto i:line_style_info[3].toArray())
        {
            pattern.append(i.toInt());
        }
        LineStyle style{line_style_info[1].toString() , line_style_info[2].toInt() , pattern};
        display->LineStyles[style.name] = style;

    }
    return display;
}

DisplayPtr &Display::ParserStipper(DisplayPtr &display, const QJsonObject &root_obj) {
    auto stipple_array = root_obj["drDefineStipple"].toArray();
    for (auto stipple_item: stipple_array) {
        auto stipple_info = stipple_item.toArray();
        auto mesh = stipple_info[2].toArray();
        int height = mesh.size();
        int width = mesh[0].toArray().size();
        QVector<QVector<int>> mesh_array;
        for (auto mesh_row: mesh) {
            QVector<int> row;
            for (auto v: mesh_row.toArray()) {
                row.append(v.toInt());
            }
            mesh_array.append(row);
        }
        auto stipple = Stipple{stipple_info[1].toString(), mesh_array,
                               width, height
        };
        display->Stipples[stipple.name] = stipple;
    }
    return display;
}

DisplayPtr &Display::ParserColor(DisplayPtr &display, const QJsonObject &root_obj) {
    auto color_array = root_obj["drDefineColor"].toArray();
    for (auto color_item: color_array) {
        auto color_info = color_item.toArray();
        bool fliker = color_info.size() == 6;
        auto color = Color{color_info[1].toString(),
                           QColor(color_info[2].toInt(), color_info[3].toInt(), color_info[4].toInt()),
                           fliker
        };
        display->Colors[color.name] = color;
    }
    return display;
}

shared_ptr<Packet> Display::GetDisplay(const QString layer, const QString &purpose) {
    return shared_ptr<Packet>();
}
